package guda.stark.web.security;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import guda.grape.beans.JsonResult;
import guda.grape.mvc.security.PageAuthChecker;
import guda.grape.mvc.velocity.VelocityToolboxView;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpStatus;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * Created by well on 15/10/15.
 */
public class DefaultAuth implements PageAuthChecker.Callback<DefaultAuth.Status>{

    public static final  String sessionKey = "J_USER_KEY";

    private String loginURL;

    @Override
    public String getUserName(Status status) {
        return status.user.getLoginName();
    }

    @Override
    public String[] getRoleNames(Status status) {
        return status.user.getRoles();
    }

    @Override
    public Status onStart(PageAuthChecker.RequestContext requestContext) throws ServletException {
        HttpSession session = requestContext.httpServletRequest.getSession();
        AuthUser user = null;

        try {
            Object attribute = session.getAttribute(sessionKey);
            if(attribute != null && attribute instanceof JSONObject){
                JSONObject jsonObject = (JSONObject)attribute;
                user = JSON.parseObject(jsonObject.toJSONString(), AuthUser.class);
            }
        } catch (Exception e) {
            //log.warn("Failed to read admin from session: " + sessionKey, e);
        }

        if (user == null) {
            // 创建匿名用户
            user = new AuthUser();
            session.setAttribute(sessionKey, user);
            AuthUser.cleanThreadLocal();
        }

        AuthUser.setCurrentUser(user);

        return new Status(requestContext, user);
    }



    @Override
    public void onAllow(Status status) throws ServletException {

    }

    @Override
    public void onDeny(Status status) throws ServletException {
        if (status.requestContext.httpServletRequest.getRequestURI().endsWith(".json")) {
            response401(status.requestContext.httpServletResponse);
            return;
        }

        HttpServletRequest request = status.requestContext.httpServletRequest;
        String redirectUrl = buildRedirectUrl(request);
        String fullContextURL = VelocityToolboxView.getFullContextURL(request);
        try {
            status.requestContext.httpServletResponse.sendRedirect(fullContextURL+"/"+loginURL+"?redirectURL="+redirectUrl);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String buildRedirectUrl(HttpServletRequest request) {
        if (request == null) {
            return "";
        }
        StringBuffer targetUrl = request.getRequestURL();
        String queryString = request.getQueryString();
        if (StringUtils.isBlank(queryString)) {
            return targetUrl.toString();
        }
        return targetUrl.append("?").append(queryString).toString();
    }

    private void response401(HttpServletResponse response) {
        response.addHeader("Cache-Control", "no-cache");
        response.setContentType("application/json");
        PrintWriter out = null;
        try {
            out = response.getWriter();
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            JsonResult jsonResult = new JsonResult();
            jsonResult.setErrMsg("未授权");
            out.write(JSON.toJSONString(jsonResult.getMap()));
        } catch (Exception e) {

        } finally {
            if (out != null) {
                out.close();
            }
        }
    }

    static class Status {
        private final PageAuthChecker.RequestContext requestContext;
        private AuthUser user;

        public Status(PageAuthChecker.RequestContext requestContext, AuthUser user) {
            this.requestContext = requestContext;
            this.user = user;
        }
    }

    public void setLoginURL(String loginURL) {
        this.loginURL = loginURL;
    }
}
